package top.zsyle.sycc.service.impl;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import top.zsyle.sycc.bo.VerifySmsCodeBo;
import top.zsyle.sycc.constants.VerifyCodeConstant;
import top.zsyle.sycc.domain.MessageSms;
import top.zsyle.sycc.dto.SmsCodeDto;
import top.zsyle.sycc.exception.GlobalException;
import top.zsyle.sycc.exception.GlobalExceptionEnum;
import top.zsyle.sycc.properties.VerifyImgCodeProperties;
import top.zsyle.sycc.properties.VerifySmsCodeProperties;
import top.zsyle.sycc.service.IMessageSmsService;
import top.zsyle.sycc.service.VerifyCodeService;
import top.zsyle.sycc.utils.AssertUtil;
import top.zsyle.sycc.utils.StrUtils;
import top.zsyle.sycc.utils.VerifyCodeUtils;

import java.util.Date;
import java.util.concurrent.TimeUnit;

@Service
@Slf4j
public class VerifyCodeServiceImpl implements VerifyCodeService {

    @Autowired
    private RedisTemplate<Object,Object> redisTemplate;

    @Autowired
    private IMessageSmsService iMessageSmsService;

    @Autowired
    private VerifyImgCodeProperties verifyImgCodePro;
    @Autowired
    private VerifySmsCodeProperties verifySmsCodePro;

    /** 获取图形验证码
     * @param imageCodeKey
     * @return
     */
    @Override
    public String graph(String imageCodeKey) {
        //1、随机生成图形验证码字符串
        String imageCode = StrUtils.getComplexRandomString(verifyImgCodePro.getCodeLength());
        //2、将随机字符串设置到redis中
        redisTemplate.opsForValue().set(imageCodeKey,imageCode, verifyImgCodePro.getOverTime(), TimeUnit.MILLISECONDS);
        //3、将字符串生成图形验证码base64
        String base64Str = VerifyCodeUtils.verifyCode(verifyImgCodePro.getCodeWidth(), verifyImgCodePro.getCodeHight(), imageCode);
        return base64Str;
    }

    /**
     * 获取短信验证码
     * @param dto
     */
    @Override
    public void smsCode(SmsCodeDto dto) {
        //1.参数校验
        AssertUtil.isPhone(dto.getMobile(), GlobalExceptionEnum.COMM_PHONE_FORMAT_EXCEPTION);
        //2.获取图形验证码比较
        Object imgCodeObj = redisTemplate.opsForValue().get(dto.getImageCodeKey());
        //2.1 imageCode 为空或者过期时
        AssertUtil.isNotNull(imgCodeObj,GlobalExceptionEnum.COMM_IMAGE_CODE_IS_NULL_EXCEPTION);
        AssertUtil.isEqualsIgnoreCase((String)imgCodeObj,dto.getImageCode(),GlobalExceptionEnum.COMM_IMAGE_CODE_IS_UNEQUAL_EXCEPTION);
        //3.获取短信验证码 业务键+电话
        String redisSmsKey = String.format(VerifyCodeConstant.REDIS_REGISTER_PHONE, dto.getMobile());
        Object smsObj = redisTemplate.opsForValue().get(redisSmsKey);
        Date date = new Date();
        //获取短信验证码
        String code = "";
        //3.1 存在并且间隔时间小于60s(60000毫秒)
        code = saveRedisSmsCode(redisSmsKey, smsObj, date);
        //6.保存短信验证码日志,发送短信验证码
        saveMessage(date, code);
    }

    private String saveRedisSmsCode(String redisSmsKey, Object smsObj, Date date) {
        String code;
        VerifySmsCodeBo verifySmsCodeBo = new VerifySmsCodeBo();
        if (smsObj != null){
            verifySmsCodeBo = (VerifySmsCodeBo) smsObj;
            boolean boo = date.getTime()-verifySmsCodeBo.getTime()> verifySmsCodePro.getIntervalTime();
            AssertUtil.isTrue(boo,GlobalExceptionEnum.COMM_NO_MORE_THAN_INTERVAL_TIME_EXCEPTION);
            code = verifySmsCodeBo.getCode();
        }else {
            code = StrUtils.getRandomString(verifySmsCodePro.getCodeLength());
        }
        verifySmsCodeBo.setCode(code);
        verifySmsCodeBo.setTime(date.getTime());
        //4.保存到redis
        redisTemplate.opsForValue().set(redisSmsKey,verifySmsCodeBo,verifyImgCodePro.getOverTime(), TimeUnit.MILLISECONDS);
        Object o = redisTemplate.opsForValue().get(redisSmsKey);

        return code;
    }

    private void saveMessage(Date date, String code) {
        MessageSms messageSms = new MessageSms();
        messageSms.setTitle(verifySmsCodePro.getMessageTitle());
        String content = String.format(verifySmsCodePro.getContent(), code,verifySmsCodePro.getOverTime()/ verifySmsCodePro.getMillisecondsToMinute());
        messageSms.setContent(content);
        String ip = ((ServletRequestAttributes)RequestContextHolder.getRequestAttributes()).getRequest().getRemoteAddr();
        messageSms.setIp(ip);
        messageSms.setSendTime(date);
        iMessageSmsService.insert(messageSms);
        //发送短信验证码
        log.info(content);
    }

}
